package com.eliza.v.http.verify

import com.eliza.v.http.VertxTools
import io.vertx.core.AbstractVerticle
import io.vertx.core.Promise
import io.vertx.core.Vertx
import io.vertx.core.VertxOptions
import io.vertx.core.http.Cookie
import io.vertx.core.http.HttpMethod
import io.vertx.core.json.JsonObject
import io.vertx.ext.auth.KeyStoreOptions
import io.vertx.ext.auth.authorization.AuthorizationProvider
import io.vertx.ext.auth.authorization.PermissionBasedAuthorization
import io.vertx.ext.auth.jwt.JWTAuth
import io.vertx.ext.auth.jwt.JWTAuthOptions
import io.vertx.ext.web.Router
import io.vertx.ext.web.RoutingContext
import io.vertx.ext.web.Session
import io.vertx.ext.web.handler.AuthorizationHandler
import io.vertx.ext.web.handler.JWTAuthHandler
import io.vertx.ext.web.handler.SessionHandler
import io.vertx.ext.web.sstore.ClusteredSessionStore
import io.vertx.ext.web.sstore.LocalSessionStore
import io.vertx.ext.web.sstore.SessionStore


/*-*- coding:utf-8 -*-
 * @Author  : debi
 * @Time    : 2/2/22
 * @Software: IntelliJ IDEA
 */

class Verify : AbstractVerticle() {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            VertxTools.runVertical(Verify::class.java)

        }
    }

    val CC: String = "DD"
    override fun start(startPromise: Promise<Void>?) {
        super.start(startPromise)
        var path = "/Verify/getJwt"


        example51()
    }

    private fun setCookie() {
        val router = Router.router(vertx)
        router.route("/setCookie").method(HttpMethod.POST).method(HttpMethod.GET).handler { rc ->
            println("cookieCount: before ${rc.request().cookieCount()}")

            val name = rc.request().getParam("name")
            val pwd = rc.request().getParam("pwd")

            println("${name}:${pwd}")
            rc.response().addCookie(Cookie.cookie(CC, name + pwd))
            println("cookieCount after: ${rc.request().cookieCount()}")
            println("getCookie : ${rc.request().getCookie(CC)}")
            rc.end("setCookie")
        }


//        要启用无 cookie 会话：
        /*      router.route()
                  .handler(SessionHandler.create(SessionStore.create(vertx)).setCookieless(true));*/
        VertxTools.result(vertx, this, "setCookie", router, 8080)

    }


    private fun setSession() {
        val router = Router.router(vertx)
//        create(Vertx vertx, String sessionMapName)
        /**
         * 使用此存储，会话本地存储在内存中，并且仅在此实例中可用。
        用于： 只有一个 Vert.x 实例，在应用程序中使用粘性会话 将负载均衡器配置为始终将 HTTP 请求路由到同一个 Vert.x 实例
        如果您不能确保您的请求都将在同一台服务器上终止，那么请不要使用此存储，因为您的请求可能最终会在不知道您的会话的服务器上结束。
         */
        val sessionHandler = SessionHandler
            .create(LocalSessionStore.create(vertx, "sessionMap"))

        router.route("/setSession")
            .method(HttpMethod.POST)
            .method(HttpMethod.GET)
            .handler(sessionHandler)
            .handler { rc ->

                val session = rc.session()
                if (session.isEmpty) {
                    session.get<String>("session") ?: let {
                        println("First In")
                        println("Before :${session.get<String>("session")}")

                        session.put("session", "Asbb")
                    }
                    println("After :${session.get<String>("session")}")
                } else {
                    println("not Empty ")
                    session.get<String>("session")?.let {
                        println("${session.get<String>("session")} clear")
//                    session.remove<String>("session")
                    }

                }

                //遍历sessionMap 全局localMap
                vertx.setTimer(50) { l ->
                    val localMap = vertx.sharedData().getLocalMap<String, Session>("sessionMap")
                    localMap.forEach { (k, v) ->
                        println("$k:${v.data()}")
                    }
                }
                rc.end("setSession")

            }

        VertxTools.result(vertx, this, "setSession", router, 8080)
    }


    private fun ssdd() {
        /*集群会话存储
        使用此存储，会话存储在分布式映射中，可跨 Vert.x 集群访问。
            如果您不使用粘性会话，则此存储是合适的，即您的负载平衡器将来自同一浏览器的不同请求分发到不同的服务器。
            您的会话可从集群中使用此存储的任何节点访问。
            要使用集群会话存储，您应该确保您的 Vert.x 实例是集群的。*/
        Vertx.clusteredVertx(VertxOptions()) { res ->
            val vertx: Vertx = res.result()

            // Create a clustered session store using defaults
            val store1: SessionStore = ClusteredSessionStore.create(vertx)

            // Create a clustered session store specifying the distributed map name to use
            // This might be useful if you have more than one application in the cluster
            // and want to use different maps for different applications
            val store2: SessionStore = ClusteredSessionStore.create(
                vertx,
                "myclusteredapp3.sessionmap"
            )
        }

    }

    //    配置授权
    fun authorization() {
        val router = Router.router(vertx)
        val authConfig = JWTAuthOptions()
            .setKeyStore(
                KeyStoreOptions()
                    .setType("jceks")
                    .setPath("keystore.jceks")
                    .setPassword("secret")
            )

        val authProvider = JWTAuth.create(vertx, authConfig)
        router.route().handler(
            // create the handler that will perform the attestation
            AuthorizationHandler.create(
                PermissionBasedAuthorization.create("can-do-work")//证明
            )
                // where to lookup the authorizations for the user
                .addAuthorizationProvider(AuthorizationProvider.create("aa", setOf()))//添加授权提供者
        )

        VertxTools.result(vertx, this, "ssss", router, 8080)

    }

    private fun getJwt(path: String) {
        val router = Router.router(vertx)

        val authConfig = JWTAuthOptions()
            .setKeyStore(
                KeyStoreOptions()
                    .setType("jceks")
//                        http/keys/jwt/keystore.jceks
//                    .setPath("http/keys/jwt/keystore.jceks")
//                    .setPath("http/keys/jwt/keystore.jceks")
                    .setPassword("secret")
            )

        val jwt = JWTAuth.create(vertx, authConfig)



        router.route(path)
            .handler { ctx: RoutingContext ->
                // this is an example, authentication should be done with another provider...
                if ("eliza" == ctx.request().getParam("name") &&
                    "eliza" == ctx.request().getParam("pwd")
                ) {
                    ctx.response()
                    val token = jwt.generateToken(
                        JsonObject()
                            .put("eliza", "eliza")
                            .put("aaa", "asssas")
                            .put("www", "1112")

                    )//在创建令牌期间只需将数据添加到 JsonObject 参数：


                    println(token)
/*
    与用户打交道时，授权是下一个合乎逻辑的步骤。
    虽然身份验证确实特定于协议，但授权是独立的，所有信息都是从User对象中提取的。
*/
//                获取数据
                    ctx.user().principal().getString("www")

                } else {
                    ctx.fail(401)
                }
            }
//        .handler(LoggerHandler.create(LoggerFormat.CUSTOM))
//        router.route("/static/*").handler(StaticHandler.create());

        VertxTools.result(vertx, this, path, router, 8080)

    }

    fun example51() {

        val router = Router.router(vertx)
        val authConfig = JWTAuthOptions()
            .setKeyStore(
                KeyStoreOptions()
                    .setType("jceks")
                    .setPath("http/verify/keystore.jceks")
                    .setPassword("secret")
            )
        val authProvider = JWTAuth.create(vertx, authConfig)
        router.route("/protected/*").handler(JWTAuthHandler.create(authProvider))
        router.route("/protected/somepage").handler { ctx: RoutingContext? -> }
        VertxTools.result(vertx, this, "ssss", router, 8080)


    }

}